package com.xiaoran.rpc.server;

import com.xiaoran.rpc.base.RpcRequest;
import com.xiaoran.rpc.base.RpcResponse;
import com.xiaoran.rpc.util.ClassUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ServerHandler extends SimpleChannelInboundHandler<RpcRequest> {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServerHandler.class);
    private static final Map<Class<?>, Object> OBJECT_MAP = new HashMap<>();

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest request) throws Exception {
        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setRequestId(request.getRequestId());
        LOGGER.info("开始处理消息： requestId = " + request.getRequestId());
        //找到接口
        try {
            Class<?> clazz = Class.forName(request.getClassName());
            if (!OBJECT_MAP.containsKey(clazz)) {
                //找到接口的实现类，放入缓存 OBJECT_MAP 中
                ArrayList<Class> allClassByInterface = ClassUtil.getAllClassByInterface(clazz);
                for (Class c : allClassByInterface) {
                    OBJECT_MAP.put(clazz,c.newInstance());
                }
            }
            //通过反射找到⽅法执⾏
            Method method = clazz.getMethod(request.getMethodName(), request.getParameterTypes());
            method.setAccessible(true);
            Object result = method.invoke(OBJECT_MAP.get(clazz), request.getParameters());

            rpcResponse.setResult(result);
        } catch (Exception e){
            LOGGER.error("处理失败... requestId = " + request.getRequestId(), e);
            //出错
            rpcResponse.setErrorMsg("error");
        }
        channelHandlerContext.writeAndFlush(rpcResponse);
    }
}
